<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2019/11/1
 * Time: 15:42
 */

namespace app\adminapiv3\service;

use app\common\model\FilePath;
use app\common\model\RivestCipher;
use app\common\service;
use think\Db;

class ServerAuth extends Base
{
    /**
     * @name 授权列表
     * @param $params
     * @param int $limit
     * @return array
     * @author wx
     * @date 2019/11/7 13:57
     */
    function list($params, $limit = 10)
    {
        $userInfo = $this->getUserInfo();

        $server = new \app\common\service\ServerAuth();
        $list = $server->list($params, $limit, $userInfo['user_group_id']);


        //处理数据
        foreach($list['data'] as $k => $v){

            $v['stime'] = date('Y-m-d', $v['stime']);
            $v['etime'] = $v['etime'] == 0 ? '永久授权' : date('Y-m-d', $v['etime']);
            $list['data'][$k] = $v;
        }

        $is_software = db('system_config')->value('type');
        $authInfo = db('server_auth')->find();
        $authInfo['is_software'] = $is_software;

        $list['auth_info'] = $authInfo;

        return $list;
    }

    /**
     * @name 离线授权
     * @author wx
     * @date 2019/12/2 15:28
     */
    function offline($file)
    {
        //1. 上传文件
        $uploadServer = new Upload();
        $uploadAuthDir = '../runtime/Upload/Auth';
        $uploadRes = $uploadServer->upload($file, $uploadAuthDir,'key',5*1024*1024);

        if($uploadRes['code'] != 0){
            returnErrJson($this->CODE_FAIL, $uploadRes['msg']);
        }

        //2. 解密文件
        $authFile = $uploadRes['path'].$uploadRes['file_name'];

        $rc4Server = new RivestCipher();
        $content = file_get_contents($authFile);
        $authInfo = $rc4Server->decrypt($content);

        if(!$authInfo){
            returnErrJson($this->CODE_FAIL, '错误的授权文件');
        }

        foreach ($authInfo as $k => $v){
            $this->checkData($v);
            $this->checkLocal($v);
            $this->checkNumberAndTime($v);
            $this->checkAuthTime($v, $this->getSystemTime());
        }

        //4. 处理数据
        $this->handleData($authInfo);

        //5. over
        return true;
    }

    /**
     * @name: 平台授权信息
     * @Param: 
     * @Description: 
     * @Author: foo
     * @Date: 2019-11-20 17:44:33
     */
    function platformAuthInfo ()
    {
        $authInfo = db('server_auth')->field('product_name, company_name')->find();

        $authInfo['is_software'] = db('system_config')->value('type');

        //返回服务端版本
        $authInfo['product_m_version'] = $this->getPlatformVersion();

        return $authInfo;
    }

    /**
     * @name 用户授权信息
     * @author wx
     * @date 2020/11/13 11:12
     */
    public function userAuthInfo($accesstoken)
    {
        //查询当前用户
        $userInfo = db('server_user')->where('token', $accesstoken)->find();

        if(!$userInfo){
            $this->setError($this->CODE_FAIL, '未查询到用户信息');
            return false;
        }

        $userGroupInfo = db('server_user_group')->where('id',$userInfo['user_group_id'])->find();

        if(!$userInfo){
            $this->setError($this->CODE_FAIL, '未查询到用户组信息');
            return false;
        }

        $return['bind_key'] = $userGroupInfo['bind_key'];

        $return['company'] = db('server_auth')->value('unit_name');
        if($userGroupInfo['level'] != 0 && $userGroupInfo['upper_id'] != 0 && !empty($userGroupInfo['company'])){
            //非超管组
            $return['company'] = $userGroupInfo['company'];
        }

        //返回服务端版本
        $versionServer = new service\ServerVersion();
        $return['version_name'] = Db::name('server_auth')->value('version_name');

        //授权状态
        $authStatus = $this->expireDay($userInfo['user_group_id']);
        $return['auth_status'] = $authStatus['expire_msg'];

        return $return;
    }


    /**
     * @name 返回授权剩余天数
     * @param $groupId 用户组id
     * @return array
     * @author wx
     * @date 2020/12/10 11:14
     */
    public function expireDay($groupId)
    {
        $systemTime = $this->getSystemTime();//系统时间
        $groupAuthArr = db('server_user_group_module')->where('group_id', $groupId)->column('etime');

        $sDayArr = [];
        foreach ($groupAuthArr as $k => $v){
            if($v != 0){
                $sTime = $v - $systemTime;
                $sTime = $sTime < 0 ? 0 : $sTime;
                $sDayArr[] = ceil($sTime / 86400);
            }
        }

        $sMinDay = empty($sDayArr) ? 0 : min($sDayArr);//最小授权时间

        if($sMinDay == 0){
            $exprire_msg = '部分授权或全部授权已到期，请查看授权信息页面';
            $exprire_status = 1;
        }elseif ($sMinDay <= 3){
            $exprire_msg = '授权到期时间不足3天，请查看授权信息页面';
            $exprire_status = 1;
        }elseif ($sMinDay <= 5){
            $exprire_msg = '授权到期时间不足5天，请查看授权信息页面';
            $exprire_status = 1;
        }elseif ($sMinDay <= 7){
            $exprire_msg = '授权到期时间不足7天，请查看授权信息页面';
            $exprire_status = 1;
        }else{
            $exprire_msg = '授权正常';
            $exprire_status = 0;
        }

        return [
            'expire_status' => $exprire_status,
            'expire_msg' => $exprire_msg,
        ];
    }

    /**
     * @name 获取平台基本硬件信息 UUID 网卡,网关等
     * @author wx
     * @date 2019/11/28 16:06
     */
    function getPlatformBaseInfo()
    {
        $serverFile = $_SERVER['DOCUMENT_ROOT'].'/Install/.jzz.lock';

        if(!file_exists($serverFile)){//强制停止

            returnErrJson($this->CODE_FAIL, '系统主机信息文件不存在,请联系维护人员');
        }

        $content = file_get_contents($serverFile);
        $platformBaseInfo = json_decode($content, true);

        return $platformBaseInfo;
    }

    /**
     * @name 检查是否是本机授权
     * @param $info
     * @return bool
     * @author wx
     * @date 2019/11/29 15:37
     */
    function checkLocal($info)
    {
        $platformBaseInfo = $this->getPlatformBaseInfo();//平台UUID

        if ($info['uuid'] != $platformBaseInfo['hostkey']) {
            returnErrJson($this->CODE_FAIL, '不是本机授权');
        }

        return true;
    }

    /**
     * @name 验证授权时间
     * @param $info
     * @return bool
     * @author wx
     * @date 2019/11/29 15:39
     */
    function checkAuthTime($info, $nowTime)
    {
        if ($info['etime'] != 0 && $info['etime'] <= $nowTime) {
            returnErrJson($this->CODE_FAIL, '授权已到期');
        }

        return true;
    }

    /**
     * @name 检测模块授权时间和数量
     * @author wx
     * @date 2020/12/25 13:38
     */
    public function checkNumberAndTime($info)
    {
        //查询当前模块授权数据
        $moduleInfo = Db::name('server_auth_module')->where('module_key', $info['product_key'])->find();
        if($moduleInfo){
            if ($moduleInfo['number'] > $info['number']) {
                returnErrJson($this->CODE_FAIL, $moduleInfo['module_name'].'模块授权数量不能少于'.$moduleInfo['number']);
            }

            if ($info['etime'] != 0 && $moduleInfo['etime'] > $info['etime']) {
                returnErrJson($this->CODE_FAIL, $moduleInfo['module_name'].'模块授权时间不能少于'.date('Y-m-d', $moduleInfo['etime']));
            }
        }

        return true;
    }

    /**
     * @name 验证数据是否符合标准
     * @param $info
     * @author wx
     * @date 2019/11/29 15:41
     */
    function checkData($info)
    {

        $array = array(
            'unit_name',
            'auth_key',
            'company_name',
            'product_id',
            'product_name',
            'module_name',
            'product_key',
            'product_m_version',
            'product_c_version',
            'number',
            'stime',
            'etime',
            'type',
            'mode',
            'is_port',
            'address_json',
            'uuid',
            'maintain_password',
            'is_software',
            'version_name',
            'version_key',
        );

        foreach ($array as $v){
            if (!isset($info[$v])) {
                returnErrJson($this->CODE_FAIL, '错误的授权文件');
            }
        }

        return true;
    }

    /**
     * @name 生成hostkey
     * @return bool
     * @author wx
     * @date 2019/12/2 13:32
     */
    function createHostFile()
    {
        $dir = 'static/host/';
        $fileName = 'hostkey.key';

        if (!file_exists($dir.$fileName)) {

            if (!file_exists($dir)) {
                mkdir($dir, 0777, true);
            }

            $serverInfo = $this->getPlatformBaseInfo();

            $requestData = array(
                'ip' => $_SERVER['SERVER_ADDR'],
                'system' => $serverInfo['os'],
                'alias' => $serverInfo['hostname'],
                'uuid' => $serverInfo['hostkey'],
            );

            $rc4Server = new RivestCipher();
            $rc4Data = $rc4Server->encrypt($requestData);

            file_put_contents($dir.$fileName, $rc4Data);
        }

        return true;
    }

    /**
     * @name 授权数据处理
     * @param $authArr
     * @author wx
     * @date 2019/12/2 14:56
     */
    function handleData($authArr, $is_install = 0)
    {
        if ($is_install == 1) {
            $systemTime = time();
        }else{
            $systemTime = $this->getSystemTime();
        }

        $dbConf = config('database.');
        $tableModuleName = $dbConf['prefix'].'host_module_relation';


        foreach ($authArr as $k => $v){

            //1. 修改模块表
            $moduleId = db('server_auth_module')->where('module_key', $v['product_key'])->value('id');
            $moduleData = [
                'module_name' => $v['module_name'],
                'module_key' => $v['product_key'],
                'number' => $v['number'],
                'stime' => $v['stime'],
                'etime' => $v['etime'],
                'product_c_version' => $v['product_c_version'],
                'is_port' => $v['is_port'],
            ];

            if($moduleId){//更新
                db('server_auth_module')->where('id', $moduleId)->update($moduleData);
            }else{//添加
                $moduleId = db('server_auth_module')->insertGetId($moduleData);
            }

            //创建模块
            $moduleName = $v['product_key'];
            $moduleComment = $v['product_name'];
            $hostModuleServer = new \app\common\model\HostModuleRelation();
            $fieldNum = $hostModuleServer->checkField($moduleName);

            if($fieldNum == 0){//创建模块
                $createModule = "ALTER TABLE `$tableModuleName` ADD COLUMN `$moduleName`  tinyint(1) NOT NULL DEFAULT 0 COMMENT '$moduleComment';";
                db()->query($createModule);
            }

            //3. 修改超级管理员授权数量,时间
            $groupId = db('server_user_group')->where(['upper_id' => 0, 'level' => 0])->value('id');

            $updateNum = 0;

            if($v['etime'] >=  $systemTime){

                //成功开启当前模块的主机数量
                $successOpenNum = Db::name('host h')
                    ->join('host_module_relation hmr', 'h.id = hmr.host_id')
                    ->where('group_id', $groupId)
                    ->where($v['product_key'], 1)
                    ->count();

                //需要开启的当前模块的数量
                $needOpenNum = $v['number'] - $successOpenNum;

                if($needOpenNum > 0){
                    //根据主机id从小到大开启当前模块
                    $hostIdArr = Db::name('host_module_relation hmr')
                        ->join('host h', 'h.id = hmr.host_id')
                        ->where($v['product_key'], 0)
                        ->where('group_id', $groupId)
                        ->order('host_id asc')
                        ->limit($needOpenNum)
                        ->column('host_id');

                    $updateNum = Db::name('host_module_relation')->whereIn('host_id', $hostIdArr)->update([$v['product_key'] => 1]);
                }

            }

            $groupAuthData = [
                'group_id' => $groupId,
                'module_id' => $moduleId,
                'total' => $v['number'],
                'used' => Db::raw("used + {$updateNum}"),
                'etime' => $v['etime'],
            ];

            $authId = db('server_user_group_module')->where(['group_id' => $groupId, 'module_id' => $moduleId])->value('id');
            if($authId){
                db('server_user_group_module')->where(['group_id' => $groupId, 'module_id' => $moduleId])->update($groupAuthData);
            }else{
                db('server_user_group_module')->where(['id' => $authId])->insert($groupAuthData);
            }

            $is_software = $v['is_software'];
            $product_m_version = $v['product_m_version'];

            $Data = array(
                'unit_name' => $v['unit_name'],
                'auth_key' => $v['auth_key'],
                'company_name' => $v['company_name'],
                'product_id' => $v['product_id'],
                'product_name' => $v['product_name'],
                'product_m_version' => $v['product_m_version'],
                'mode' => $v['mode'],
                'address_json' => $v['address_json'],
                'version_name' => $v['version_name'],
                'version_key' => $v['version_key'],
            );
        }


        //修改授权主表
        $authInfo = db('server_auth')->find();

        //处理总授权表
        if(empty($authInfo)){
            db('server_auth')->insert($Data);
        }else{
            //修改
            db('server_auth')->where('id', $authInfo['id'])->update($Data);
        }

        //5. 修改软件硬件版本
        db('system_config')->where('id', 1)->update(['type' => $is_software]);
    }

    /**
     * @name 在线授权
     * @author wx
     * @date 2019/12/2 15:24
     */
    function online($key)
    {
        $serverInfo = $this->getPlatformBaseInfo();

        $requestData = array(
            'serial_number' => $key,
            'ip' => $_SERVER['SERVER_ADDR'],
            'system' => $serverInfo['os'],
            'alias' => $serverInfo['hostname'],
            'uuid' => $serverInfo['hostkey'],
        );

        $fileServer = new FilePath();
        $url = $fileServer->remote_auth_domain.'/api/v3/activation/register/online';

        $authRes = requestCurl($url,1,$requestData);

        if($authRes['code'] != 200){
            returnErrJson($authRes['code'], $authRes['msg']);
        }

        $authData = $authRes['data'];
        foreach ($authData as $k => $v){
            $this->checkData($v);
            $this->checkLocal($v);
            $this->checkNumberAndTime($v);
            $this->checkAuthTime($v, $this->getSystemTime());
        }

        $this->handleData($authData);

        return true;
    }



    /**
     * @name 获取系统时间
     * @return mixed
     * @author wx
     * @date 2019/12/10 14:47
     */
    function getSystemTime()
    {
        $fileServer = new FilePath();
        $systemTimeFile = $fileServer->system_time;

        if(!file_exists($systemTimeFile)){
            returnErrJson(101, '系统时间文件不存在,请联系维护人员');
        }
        $content = file_get_contents($systemTimeFile);
        $systemTime = json_decode($content,true);

        if (!isset($systemTime['stime'])) {
            returnErrJson(101, '系统时间文件错误,请联系维护人员');
        }

        $nowTime = ceil($systemTime['stime']);

        return $nowTime;
    }

    /**
     *  获取用户组授权数量
     */
    function groupAuthNum($groupId = 0)
    {
        $db = db('server_user_group');
        if($groupId != 0){
            $db->where('id', $groupId);
        }

        $info = $db->field('SUM(auth_number) as auth_number')->find();


    }

    /**
     * @name 获取平台版本号
     * @return bool|string
     * @author wx
     * @date 2020/11/13 15:54
     */
    public function getPlatformVersion()
    {
        $paltformVersion = Db::name('host')->where('group_id', -1)->value('client_version');

        return $paltformVersion;
    }

    /**
     * @name 设置平台版本号
     * @return bool|string
     * @author wx
     * @date 2020/11/13 15:54
     */
    public function setPlatformVersion($platformVersion)
    {
        $paltformVersion = Db::name('host')->where('group_id', -1)->update(['client_version' => $platformVersion]);

        return $paltformVersion;
    }

}